package com.raising.framework.shiro.realm;


import com.raising.framework.shiro.entity.CurrentUser;
import com.raising.modules.sys.entity.User;
import com.raising.modules.sys.service.UserService;
import com.raising.utils.PasswordUtils;
import com.raising.utils.UserUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.PostConstruct;
import java.util.Set;

/**
 * 用户权限认证
 * @author gaoy
 */
public class MyUserRealm extends AuthorizingRealm {

	private static final Logger logger = LoggerFactory.getLogger(MyUserRealm.class);

	@Autowired
	private UserService userService;

	/**
	 * 授权信息
	 * 只有登录才会授权
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		if(logger.isDebugEnabled()){
			logger.debug("【Shiro】>>> MyUserRealm.doGetAuthorizationInfo()，封装授权信息 -> AuthorizationInfo");
		}
		SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
		User user = UserUtils.getLoginUser();
		if(user == null || user.getRoleIds() == null || user.getRoleIds().size() == 0){
			return authorizationInfo;
		}
		// 角色授权
		authorizationInfo.setRoles(userService.findRoles(user.getRoleIds()));
		Set<String> stringPermissions = userService.findPermissions(user.getRoleIds());
		// 权限授权
		authorizationInfo.setStringPermissions(stringPermissions);
		return authorizationInfo;
	}

	/**
	 * 登录认证信息
	 * 登录时验证、校验密码
	 * @author gaoy
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
		if(logger.isDebugEnabled()){
			logger.debug("【Shiro】>>> MyUserRealm.doGetAuthenticationInfo()，封装认证信息 -> AuthenticationInfo");
		}
		MyUsernamePasswordToken token = (MyUsernamePasswordToken) authcToken;  
		String username = (String) token.getPrincipal();
		User user = userService.selectUserInfoByUserName(username);
		if (user == null) {
			// 没找到帐号
			throw new UnknownAccountException();
		}
		if (Boolean.TRUE.equals(user.getLocked())) {
			// 帐号锁定
			throw new LockedAccountException();
		}

		CurrentUser currentUser = new CurrentUser();
		currentUser.setId(user.getId());
		currentUser.setUsername(username);
		currentUser.setOrgId(user.getOrgId());
		currentUser.setOrgNm(user.getOrgNm());
		currentUser.setOrgNo(user.getOrgNo());
		currentUser.setRoleIds(user.getRoleIdsStr());

		/**
		 * 交给AuthenticatingRealm使用CredentialsMatcher进行密码匹配
		 * 第一个参数就是 缓存对象 可以通过 SecurityUtils.getSubject() 获取
		 */
		SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
				// 当前登录用户对象
				currentUser,
				// 密码
				user.getPassword(),
				// 加密盐
				ByteSource.Util.bytes(PasswordUtils.PRE + user.getSalt()),
				getName()
		);
		return authenticationInfo;
	}

	/**
	 * 清除用户授权信息缓存
	 * @param principals
	 */
	@Override
	public void clearCachedAuthorizationInfo(PrincipalCollection principals) {
		super.clearCachedAuthorizationInfo(principals);
	}

	/**
	 * 清除登录认证信息缓存
	 * @author GaoYuan
	 * @date 2018/11/20 下午4:33
	 */
	@Override
	public void clearCachedAuthenticationInfo(PrincipalCollection principals) {
		super.clearCachedAuthenticationInfo(principals);
	}

	@Override
	public void clearCache(PrincipalCollection principals) {
		super.clearCache(principals);
	}
	
	@PostConstruct
    public void initCredentialsMatcher() {
		//该句作用是重写shiro的密码验证，让shiro用我自己的验证
        setCredentialsMatcher(new MyCredentialsMatcher());
    }

}
